import fs from "fs";
import path from "path";
import { isDirectory } from "../utils/tools";
import { NextFunction, Request, Response, Router } from "express";
import createError from "http-errors";
import errorHandler from "../common/middlewares/errorHandler";
import verificationToken, { IVerificationWhiteList } from "../common/middlewares/verificationToken";
import { IRouterExport } from "../common/CommonType";


// router文件名（不包括后缀）
const MODULE_FILE_NAME = "Router";
const REQUEST_PREFIX = "/api"

interface IRoutes {
  url: string;
  router: Router;
}

export const routerSetup = async (app: any) => {
  const whiteList: IVerificationWhiteList[] = [];
  const routes: IRoutes[] = [];

  const handler = async (originPath: string) => {
    const dirs = await fs.promises.readdir(originPath);

    for (const filename of dirs) {
      const target = path.resolve(originPath, filename)

      // 是否为目录
      if (await isDirectory(target)) {
        await handler(target)
      } else if (path.basename(filename, path.extname(filename)) === MODULE_FILE_NAME) {
        // 是model则导入
        const modelPath = path.resolve(originPath, path.basename(filename, path.extname(filename)))
        const module = await import(modelPath);
        const routerInfo = module.default as IRouterExport;

        if (routerInfo.requestPath) {
          const url = REQUEST_PREFIX + routerInfo.requestPath;

          // 构建路由
          routes.push({
            url,
            router: routerInfo.router
          })

          // 构建白名单
          if (routerInfo.whiteList) {
            routerInfo.whiteList.forEach(item => {
              item.path = REQUEST_PREFIX + item.path;
            })
            whiteList.push(...routerInfo.whiteList)
          }
        }
      }
    }
  }


  await handler(__dirname)

  // 注册验证token路由
  app.use("/", verificationToken(whiteList));

  // 注册路由
  for (const route of routes) {
    app.use(route.url, route.router)
  }

  // 404
  app.use((_req: Request, _res: Response, next: NextFunction) => {
    next(createError(404));
  });

  // 错误处理
  app.use(errorHandler);
}
